'''
Created on Jul 9, 2011

@author: kafkef
'''

import time

from PyQt4.QtGui import *
from PyQt4.QtCore import SIGNAL, SLOT, pyqtSlot, QObject, Qt, QStringList, QSize

from dexen.system.client import ui
from dexen.system.client.ui import resource
from dexen.system.common.states import JobState
from dexen.system.client.ui.dialogs.new_job_dlg import NewJobDialog
from dexen.system.client.proxy import JobProxy

svr_proxy = ui.svr_proxy


class Roles(object):
    JobIdRole = Qt.UserRole + 1


class JobListWidget(QTreeWidget):
    def __init__(self, parent=None):
        QTreeWidget.__init__(self, parent)
        # Configure the column properties
        self.setColumnCount(2)
        # Configure the header
        header_labels = QStringList()
        header_labels << "JobName" << "Status"
        self.setHeaderLabels(header_labels)
        # Configure the signal/slot connections
        QObject.connect(self, SIGNAL("currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)"),
                        self.on_cur_item_changed)

    def add_job_state(self, row, job_state):
        assert isinstance(job_state, JobState)
        list = QStringList()
        list << job_state.job_name << job_state.get_status()
        item = QTreeWidgetItem(list)
        item.setData(0, Roles.JobIdRole, job_state.job_id)
        self.addTopLevelItem(item)

    def set_job_states(self, job_states):
        for index, job_state in enumerate(job_states):
            self.add_job_state(index, job_state)
        # Highlight the first item in the list when the contents are updated.
        if self.topLevelItemCount() > 0:
            item = self.topLevelItem(0)
            assert isinstance(item, QTreeWidgetItem)
            self.setCurrentItem(item)
    
    def on_cur_item_changed(self, current, previous):
        print "current item changed", current
        if not current: return
        assert isinstance(current, QTreeWidgetItem)
        job_id = current.data(0, Roles.JobIdRole).toInt()[0]
        print "job_id is", job_id
        self.emit(SIGNAL("cur_job_changed"), job_id)


class JobNavigatorWidget(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self._create_widgets()

    def _create_widgets(self):
        # Create the widgets
        self._header_label = QLabel("Jobs")
        self._list_widget = JobListWidget()
        self._toolbar = QToolBar()
        # Configure the widgets
        self._toolbar.addAction(QIcon(":/assets/add.png"), "Run a new job",
                                self.on_new_job)
        self._toolbar.addAction(QIcon(":/assets/refresh.png"), "Refresh a job", 
                                self.on_refresh)
        self._toolbar.addAction(QIcon(":/assets/stop.png"), "Stop a job",
                                self.on_stop_job)
        self._toolbar.setIconSize(QSize(17,17))
        # Lay out the widgets
        layout = QVBoxLayout()
        layout.setMargin(0)
        layout.addWidget(self._toolbar)
        layout.addWidget(self._list_widget)
        self.setLayout(layout)
        
        # Configure the signal/slot connections
        QObject.connect(self._list_widget, SIGNAL("cur_job_changed"),
                        self.on_cur_job_changed)   
    
    def _refresh_list(self):
        job_states = svr_proxy.get_job_states()
        self._list_widget.clear()
        self._list_widget.set_job_states(job_states)

    def on_new_job(self):
        self.new_job_dlg = NewJobDialog(self)
        ret_value = self.new_job_dlg.exec_()
        if ret_value == QDialog.Accepted:
            time.sleep(2)
            self._refresh_list()
    
    def on_stop_job(self):
        item = self._list_widget.currentItem()
        assert isinstance(item, QTreeWidgetItem)
        job_id = item.data(0, Roles.JobIdRole).toInt()[0]
        job_proxy = svr_proxy.get_job_cached(job_id)
        assert isinstance(job_proxy, JobProxy)
        job_proxy.stop()
        # TODO: on_refresh will cause the entire list to be updated.
        # However, we only want to stop the specified job without possibly
        # changing the contents of the list since the on_refresh might change
        # contents of the list.
        self.on_refresh()
        
    def on_refresh(self):
        print 'on_refresh'
        self._refresh_list()
        self.emit(SIGNAL("on_refresh"))
        
    def on_server_connected(self):
        self._refresh_list()
    
    def on_cur_job_changed(self, job_id):
        self.emit(SIGNAL("cur_job_changed"), job_id)
            
